October 2019

[Script run 2019-10-31 16:37:54]


# Bind confidence trials to non-confidence ones
AdvisedTrial <- safeBind(list(AdvisedTrial, AdvisedTrialWithConf))

# Drop participants tagged with 'test'
dropList <- okayIds$pid[grepl('test', okayIds$tags)]
AdvisedTrial <- dplyr::filter(AdvisedTrial, !(pid %in% dropList))
nameList <- names(AdvisedTrial)[grepl('.distance', names(AdvisedTrial))]

for (i in 1:nrow(AdvisedTrial)) {
  for (n in nameList) {
    if (!is.na(AdvisedTrial[i, n])) {
      AdvisedTrial[i, paste0('advisor0', reFirstMatch('\\.(\\w+)*', n))] <-
        AdvisedTrial[i, n]
    }
  }
}

Introduction

We want to explore how weight on advice differs as a function of advice distance over all the participants we’ve ever collected data from.

Analyses

Visualisation


ggWhole <- AdvisedTrial %>% ggplot(aes(x = advisor0distance, y = advisor0woa)) +
  geom_point(alpha = .2) +
  geom_smooth(se = F)

ggWhole

It is encouraging to see that the u-shaped relationship we expect is present in the sample as a whole. Next we’ll look to see what the best quadratic fit is.

mLinear <- lm(advisor0woa ~ advisor0distance, AdvisedTrial)
mQuadratic <- lm(advisor0woa ~ advisor0distance + I(advisor0distance ^ 2), 
                 AdvisedTrial)

BIC <- function(model) {
  LogLikelihood <- sum(log(dnorm(model$residuals)))
  log(length(model$residuals)) * (length(model$coefficients) + 1) - 
    2 * LogLikelihood
}

The linear and quadratic models can be compared for significant improvement and using Bayesian Information Criterion, which adjusts for the number of parameters in the model.


anova(mLinear, mQuadratic)
Analysis of Variance Table

Model 1: advisor0woa ~ advisor0distance
Model 2: advisor0woa ~ advisor0distance + I(advisor0distance^2)
  Res.Df    RSS Df Sum of Sq      F    Pr(>F)    
1  10259 1668.9                                  
2  10258 1624.9  1    44.011 277.84 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
tribble(
  ~model, ~BIC,
  'linear', BIC(mLinear),
  'quadratic', BIC(mQuadratic)
)
NA

a <- coef(mQuadratic)[1]
b <- coef(mQuadratic)[2]
c <- coef(mQuadratic)[3]

ggWhole +
  stat_function(fun = ~ a + b * .x + c * (.x ^ 2), colour = 'red')

Whole sample summary

There are two key observations: that the proposed non-linear relationship exists between distance and weight-on-advice, and that middle-of-the-road responses appear to become less frequent as distance increases. This latter point may be an illusion because there are far fewer cases on the extremes. It’s worth understanding them in some detail, however, so we’ll do some digging…

Sidenote: Frequency of extremes by distance

We’ll categorise extreme advice taking as <.05 | >.95.


AdvisedTrial <- AdvisedTrial %>%
  mutate(woaIsExtreme = advisor0woa < .05 | advisor0woa > .95,
         distanceBin = cut(advisor0distance, 10))

AdvisedTrial %>% 
  group_by(distanceBin) %>%
  summarise(m = mean(woaIsExtreme, na.rm = T), 
            s = sd(woaIsExtreme, na.rm = T),
            n = n()) %>%
  ggplot(aes(x = distanceBin, y = m)) +
  geom_rect(ymin = -Inf, ymax = 0, xmin = -Inf, xmax = Inf, fill = 'grey80') +
  geom_rect(ymin = 1, ymax = Inf, xmin = -Inf, xmax = Inf, fill = 'grey80') +
  geom_point() +
  geom_errorbar(aes(ymin = m - s, ymax = m + s), width = 0) +
  geom_smooth(aes(group = 1), method = 'lm', se = F, fullrange = T) + 
  scale_y_continuous(breaks = seq(0, 1, 0.2)) +
  geom_text(aes(y = max(m) + max(s), label = n)) +
  labs(y = 'P(WoA is extreme)',
       title = 'Extreme (<.05, >.95) WoA proportions by distance',
       subtitle = 'Numbers at the top show the number of cases in each bin')

While we ought to take the latter bins with caution, given how few trials had such extreme advice differences, we can nevertheless see an increase in the proportion of extreme advice taking as the distance increases.

By participant

We want to examine data by participant to see if they individually show the pattern. For each participant we can ask if the quadratic model is an improvement over the linear model.

We can also plot the best-fitting functions for each participant.


coefs %>% ggplot(aes(x = "coefficient", y = estimate, 
                     ymin = estimate - std.error,
                     ymax = estimate + std.error)) +
  geom_point(position = "jitter", alpha = .1) +
  facet_grid(term ~ model, scales = 'free')


tmp <- coefs %>% dplyr::filter(model == "quadratic") %>%
  dplyr::select(p:estimate) %>%
  spread(term, estimate) 

data <- NULL

for (x in 0:100) {
  data <- rbind(data, tibble(
    p = tmp$p,
    x,
    intercept = tmp$`(Intercept)`,
    distance = tmp$dist,
    distanceSquared = tmp$`I(dist^2)`,
    woa = tmp$`(Intercept)` + tmp$dist * x + tmp$`I(dist^2)` * (x ^ 2)
  ))
}

data %>% dplyr::filter(woa > 0 & woa < 1) %>%
  ggplot(aes(x, woa, colour = distance > 0, group = p)) +
  geom_line(alpha = .25) +
  scale_colour_discrete() + 
  stat_function(fun = ~ a + b * .x + c * (.x ^ 2), colour = 'red') +
  theme(legend.position = 'bottom')

The above is pretty messy - we can instead look at this within a participant by splitting up the advice they received into distance bins and computing their weight on advice by each bin. This is a less objective measure, but it seems plausible that participants calibrate to the expected distances of the advice during the task.


byP <- byP %>%
  mutate(distanceBinByP = as.numeric(cut(dist, 5)))

byP$distanceBinByP <- factor(byP[['distanceBinByP']])

# remove participants with fewer than 5 distance categories
tmp <- byP %>% 
  group_by(p, distanceBinByP) %>%
  summarise(dist = mean(dist)) 
tmp <- aggregate(distanceBinByP ~ p, tmp, length) %>%
  dplyr::filter(distanceBinByP < 5)

byPsub <- byP %>% 
  dplyr::filter(p %in% tmp$p) %>%
  ungroup(p) %>%
  mutate(p = droplevels(p)) %>%
  group_by(p)
  

# look at distribution for each participant
byPsub %>% ggplot(aes(x = distanceBinByP, y = dist,
               colour = p, group = p)) +
  stat_summary(geom = 'point', fun.y = mean, alpha = .25, position = 'jitter') +
  scale_color_discrete(guide = 'none') +
  labs(title = 
         'Mean distance of trial in each distance bin for each participant')


# run models for each participant
byPsub$distanceBinByP <- as.numeric(byPsub$distanceBinByP)

linear <- byPsub %>% 
  do(model = lm(woa ~ distanceBinByP, data = .)) 

quadratic <- byPsub %>% 
  do(model = lm(woa ~ distanceBinByP + I(distanceBinByP ^ 2), data = .)) 

bothModels <- left_join(glance(linear, model), glance(quadratic, model), 
                        by = 'p', suffix = c('.lin', '.quad')) %>%
  mutate(bestModel = if_else(BIC.quad > BIC.lin, 'Quadratic', 'Linear')) 
essentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliable
coefs <- rbind(
  linear %>% tidy(model) %>% mutate(model = 'linear'),
  quadratic %>% tidy(model) %>% mutate(model = 'quadratic')
)
essentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliableessentially perfect fit: summary may be unreliable
bothModels %>%
  ungroup() %>%
  summarise(P.quadModelBetter = mean(bestModel == 'Quadratic'))

bothModels %>% gather('model', 'BIC', 
                      c(which(grepl('BIC.', names(bothModels))))) %>%
  ggplot(aes(x = model, y = BIC)) + 
  geom_violin() + 
  geom_line(aes(group = p, colour = bestModel == 'Quadratic'), 
            alpha = .1, position = "jitter") +
  scale_y_log10() +
  labs(y = 'log10(BIC)') 

NA
NA

coefs %>% ggplot(aes(x = "coefficient", y = estimate, 
                     ymin = estimate - std.error,
                     ymax = estimate + std.error)) +
  geom_point(position = "jitter", alpha = .1) +
  facet_grid(term ~ model, scales = 'free')


tmp <- coefs %>% dplyr::filter(model == "quadratic") %>%
  dplyr::select(p:estimate) %>%
  spread(term, estimate) 


cuts <- quantile(AdvisedTrial$advisor0distance, seq(0, .9, length = 6))

data <- NULL
overallModel <- NULL

for (x in 0:5) {
  data <- rbind(data, tibble(
    p = tmp$p,
    adviceDistance = x,
    intercept = tmp$`(Intercept)`,
    distance = tmp$distanceBinByP,
    distanceSquared = tmp$`I(distanceBinByP^2)`,
    woa = tmp$`(Intercept)` + 
      tmp$distanceBinByP * x + 
      tmp$`I(distanceBinByP^2)` * (x ^ 2)
  ))
  overallModel <- rbind(overallModel, tibble(
    adviceDistance = x,
    intercept = a,
    distance = b,
    distanceSquared = c,
    woa = a + b * cuts[x] + c * (cuts[x] ^ 2)
  ))
}


data %>% #dplyr::filter(woa > 0 & woa < 1) %>%
  ggplot(aes(x = adviceDistance,y = woa, colour = distance > 0, group = p)) +
  geom_line(alpha = .25) +
  scale_colour_discrete() + 
  geom_line(data = overallModel, colour = 'red') +
  theme(legend.position = 'bottom')

Credits

Acknowledgements

Thanks as always to Nick Yeung and the other folks at the ACC Lab.

R Packages

# list packages
packageNames <- (.packages())
# don't include very core package
packageNames <- packageNames[!(packageNames %in% 
                                 rownames(installed.packages(
                                   priority = "base")))]
# but do include the base package
packageNames <- c("base", packageNames)
out <- NULL
for (p in packageNames) {
  out <- rbind(out, data.frame('Package' = p, 
                               'Citations' = paste(format(citation(p), 
                                                          style = 'textVersion'), 
                                                   collapse = '<br/><br/>')))
}

kable(out)

Funding

Matt Jaquiery is funded by a studentship from the Medical Research Council (reference 1943590) and the University of Oxford Department of Experimental Psychology (reference 17/18_MSD_661552).

Technical details

cat(paste('Time stamp:', Sys.time(), '\n\n'))
cat('Runtime \n')
proc.time()
cat('\n')
sessionInfo()
LS0tDQp0aXRsZTogIldlaWdodCBvbiBhZHZpY2UgYnkgYWR2aWNlIGRpc3RhbmNlIg0KYXV0aG9yOiAiTWF0dCBKYXF1aWVyeSAobWF0dC5qYXF1aWVyeUBwc3kub3guYWMudWspIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAzDQogICAgY3NzOiAuLi9zcmMvd3JpdGVVcC5jc3MNCiAgICBpbmNsdWRlczoNCiAgICAgIGFmdGVyX2JvZHk6IC4uL3NyYy90b2NfbWVudS5odG1sDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6ICczJw0KICAgIGNzczogLi4vc3JjL3dyaXRlVXAuY3NzDQogICAgaW5jbHVkZXM6DQogICAgICBhZnRlcl9ib2R5OiAuLi9zcmMvdG9jX21lbnUuaHRtbA0KZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpPY3RvYmVyIDIwMTkNCg0KW1NjcmlwdCBydW4gYHIgU3lzLnRpbWUoKWBdDQoNCg0KYGBge3IgcHJlbWF0dGVyLCBpbmNsdWRlID0gRn0NCg0KbGlicmFyeSh0ZXN0dGhhdCkNCg0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHN0cmluZ3IpDQoNCmxpYnJhcnkoQmF5ZXNGYWN0b3IpDQpsaWJyYXJ5KEJheWVzTWVkKQ0KDQpsaWJyYXJ5KHByZXR0eU1EKQ0KDQpsaWJyYXJ5KGJyb29tKQ0KbGlicmFyeShsbWVyVGVzdCkNCg0KbGlicmFyeShrbml0cikNCg0Kb3B0c19jaHVuayRzZXQoJ2VjaG8nID0gRikNCg0Kc2V0LnNlZWQoMjAxOTEwMDEpDQoNCiMgUGxvdCBzZXR1cA0KdGhlbWVfc2V0KHRoZW1lX2xpZ2h0KCkgKyANCiAgICAgICAgICAgIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpKQ0KDQpgYGANCg0KYGBge3IgbG9hZERhdGEsIGluY2x1ZGUgPSBGfQ0KDQoNCiMgU2VhcmNoIGFsbCBzdHVkeSBuYW1lcw0Kc3R1ZHlOYW1lIDwtICJhbGwiDQpzdHVkeVZlcnNpb24gPC0gImFsbCINCnZhcnMgPC0gbGlzdCgNCiAgJ0FkdmlzZWRUcmlhbCcgPSBsaXN0KA0KICAgIHNraXBGZWVkYmFja0NoZWNrID0gVCwNCiAgICBza2lwTWl4ZWRPZmZzZXRzID0gVA0KICAgICksDQogICdBZHZpc2VkVHJpYWxXaXRoQ29uZicgPSBsaXN0KA0KICAgIHNraXBGZWVkYmFja0NoZWNrID0gVCwNCiAgICBza2lwTWl4ZWRPZmZzZXRzID0gVA0KICAgICkNCiAgKQ0KDQpzb3VyY2UoInNyYy8wMV9Mb2FkLWRhdGEuUiIpDQoNCg0KYGBgDQoNCmBgYHtyIHRpZHkgZGF0YX0NCg0KIyBCaW5kIGNvbmZpZGVuY2UgdHJpYWxzIHRvIG5vbi1jb25maWRlbmNlIG9uZXMNCkFkdmlzZWRUcmlhbCA8LSBzYWZlQmluZChsaXN0KEFkdmlzZWRUcmlhbCwgQWR2aXNlZFRyaWFsV2l0aENvbmYpKQ0KDQojIERyb3AgcGFydGljaXBhbnRzIHRhZ2dlZCB3aXRoICd0ZXN0Jw0KZHJvcExpc3QgPC0gb2theUlkcyRwaWRbZ3JlcGwoJ3Rlc3QnLCBva2F5SWRzJHRhZ3MpXQ0KQWR2aXNlZFRyaWFsIDwtIGRwbHlyOjpmaWx0ZXIoQWR2aXNlZFRyaWFsLCAhKHBpZCAlaW4lIGRyb3BMaXN0KSkNCg0KYGBgDQoNCmBgYHtyIGFkZCB2YXJpYWJsZXN9DQpuYW1lTGlzdCA8LSBuYW1lcyhBZHZpc2VkVHJpYWwpW2dyZXBsKCcuZGlzdGFuY2UnLCBuYW1lcyhBZHZpc2VkVHJpYWwpKV0NCg0KZm9yIChpIGluIDE6bnJvdyhBZHZpc2VkVHJpYWwpKSB7DQogIGZvciAobiBpbiBuYW1lTGlzdCkgew0KICAgIGlmICghaXMubmEoQWR2aXNlZFRyaWFsW2ksIG5dKSkgew0KICAgICAgQWR2aXNlZFRyaWFsW2ksIHBhc3RlMCgnYWR2aXNvcjAnLCByZUZpcnN0TWF0Y2goJ1xcLihcXHcrKSonLCBuKSldIDwtDQogICAgICAgIEFkdmlzZWRUcmlhbFtpLCBuXQ0KICAgIH0NCiAgfQ0KfQ0KDQpgYGANCg0KIyBJbnRyb2R1Y3Rpb24NCg0KV2Ugd2FudCB0byBleHBsb3JlIGhvdyB3ZWlnaHQgb24gYWR2aWNlIGRpZmZlcnMgYXMgYSBmdW5jdGlvbiBvZiBhZHZpY2UgZGlzdGFuY2Ugb3ZlciBhbGwgdGhlIHBhcnRpY2lwYW50cyB3ZSd2ZSBldmVyIGNvbGxlY3RlZCBkYXRhIGZyb20uIA0KDQojIEFuYWx5c2VzDQoNCiMgVmlzdWFsaXNhdGlvbg0KDQpgYGB7ciB2aXN1YWxpc2F0aW9uIHdob2xlIHNhbXBsZX0NCg0KZ2dXaG9sZSA8LSBBZHZpc2VkVHJpYWwgJT4lIGdncGxvdChhZXMoeCA9IGFkdmlzb3IwZGlzdGFuY2UsIHkgPSBhZHZpc29yMHdvYSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSArDQogIGdlb21fc21vb3RoKHNlID0gRikNCg0KZ2dXaG9sZQ0KDQpgYGANCg0KSXQgaXMgZW5jb3VyYWdpbmcgdG8gc2VlIHRoYXQgdGhlIHUtc2hhcGVkIHJlbGF0aW9uc2hpcCB3ZSBleHBlY3QgaXMgcHJlc2VudCBpbiB0aGUgc2FtcGxlIGFzIGEgd2hvbGUuIE5leHQgd2UnbGwgbG9vayB0byBzZWUgd2hhdCB0aGUgYmVzdCBxdWFkcmF0aWMgZml0IGlzLg0KDQpgYGB7ciB3aG9sZSBzYW1wbGUgcXVhZHJhdGljfQ0KbUxpbmVhciA8LSBsbShhZHZpc29yMHdvYSB+IGFkdmlzb3IwZGlzdGFuY2UsIEFkdmlzZWRUcmlhbCkNCm1RdWFkcmF0aWMgPC0gbG0oYWR2aXNvcjB3b2EgfiBhZHZpc29yMGRpc3RhbmNlICsgSShhZHZpc29yMGRpc3RhbmNlIF4gMiksIA0KICAgICAgICAgICAgICAgICBBZHZpc2VkVHJpYWwpDQoNCkJJQyA8LSBmdW5jdGlvbihtb2RlbCkgew0KICBMb2dMaWtlbGlob29kIDwtIHN1bShsb2coZG5vcm0obW9kZWwkcmVzaWR1YWxzKSkpDQogIGxvZyhsZW5ndGgobW9kZWwkcmVzaWR1YWxzKSkgKiAobGVuZ3RoKG1vZGVsJGNvZWZmaWNpZW50cykgKyAxKSAtIA0KICAgIDIgKiBMb2dMaWtlbGlob29kDQp9DQpgYGANCg0KVGhlIGxpbmVhciBhbmQgcXVhZHJhdGljIG1vZGVscyBjYW4gYmUgY29tcGFyZWQgZm9yIHNpZ25pZmljYW50IGltcHJvdmVtZW50IGFuZCB1c2luZyBCYXllc2lhbiBJbmZvcm1hdGlvbiBDcml0ZXJpb24sIHdoaWNoIGFkanVzdHMgZm9yIHRoZSBudW1iZXIgb2YgcGFyYW1ldGVycyBpbiB0aGUgbW9kZWwuIA0KDQpgYGB7ciB3aG9sZSBzYW1wbGUgbW9kZWwgY29tcGFyaXNvbn0NCg0KYW5vdmEobUxpbmVhciwgbVF1YWRyYXRpYykNCg0KdHJpYmJsZSgNCiAgfm1vZGVsLCB+QklDLA0KICAnbGluZWFyJywgQklDKG1MaW5lYXIpLA0KICAncXVhZHJhdGljJywgQklDKG1RdWFkcmF0aWMpDQopDQoNCmBgYA0KDQpgYGB7ciB3aG9sZSBzYW1wbGUgbW9kZWwgcGxvdH0NCg0KYSA8LSBjb2VmKG1RdWFkcmF0aWMpWzFdDQpiIDwtIGNvZWYobVF1YWRyYXRpYylbMl0NCmMgPC0gY29lZihtUXVhZHJhdGljKVszXQ0KDQpnZ1dob2xlICsNCiAgc3RhdF9mdW5jdGlvbihmdW4gPSB+IGEgKyBiICogLnggKyBjICogKC54IF4gMiksIGNvbG91ciA9ICdyZWQnKQ0KDQpgYGANCg0KIyMgV2hvbGUgc2FtcGxlIHN1bW1hcnkgey5zdW1tYXJ5fQ0KDQpUaGVyZSBhcmUgdHdvIGtleSBvYnNlcnZhdGlvbnM6IHRoYXQgdGhlIHByb3Bvc2VkIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwIGV4aXN0cyBiZXR3ZWVuIGRpc3RhbmNlIGFuZCB3ZWlnaHQtb24tYWR2aWNlLCBhbmQgdGhhdCBtaWRkbGUtb2YtdGhlLXJvYWQgcmVzcG9uc2VzIGFwcGVhciB0byBiZWNvbWUgbGVzcyBmcmVxdWVudCBhcyBkaXN0YW5jZSBpbmNyZWFzZXMuIFRoaXMgbGF0dGVyIHBvaW50IG1heSBiZSBhbiBpbGx1c2lvbiBiZWNhdXNlIHRoZXJlIGFyZSBmYXIgZmV3ZXIgY2FzZXMgb24gdGhlIGV4dHJlbWVzLiBJdCdzIHdvcnRoIHVuZGVyc3RhbmRpbmcgdGhlbSBpbiBzb21lIGRldGFpbCwgaG93ZXZlciwgc28gd2UnbGwgZG8gc29tZSBkaWdnaW5nLi4uDQoNCiMjIFNpZGVub3RlOiBGcmVxdWVuY3kgb2YgZXh0cmVtZXMgYnkgZGlzdGFuY2UNCg0KV2UnbGwgY2F0ZWdvcmlzZSBleHRyZW1lIGFkdmljZSB0YWtpbmcgYXMgPC4wNSB8ID4uOTUuIA0KDQpgYGB7ciBleHRyZW1lcyB2aXN1YWxpc2F0aW9ufQ0KDQpBZHZpc2VkVHJpYWwgPC0gQWR2aXNlZFRyaWFsICU+JQ0KICBtdXRhdGUod29hSXNFeHRyZW1lID0gYWR2aXNvcjB3b2EgPCAuMDUgfCBhZHZpc29yMHdvYSA+IC45NSwNCiAgICAgICAgIGRpc3RhbmNlQmluID0gY3V0KGFkdmlzb3IwZGlzdGFuY2UsIDEwKSkNCg0KQWR2aXNlZFRyaWFsICU+JSANCiAgZ3JvdXBfYnkoZGlzdGFuY2VCaW4pICU+JQ0KICBzdW1tYXJpc2UobSA9IG1lYW4od29hSXNFeHRyZW1lLCBuYS5ybSA9IFQpLCANCiAgICAgICAgICAgIHMgPSBzZCh3b2FJc0V4dHJlbWUsIG5hLnJtID0gVCksDQogICAgICAgICAgICBuID0gbigpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gZGlzdGFuY2VCaW4sIHkgPSBtKSkgKw0KICBnZW9tX3JlY3QoeW1pbiA9IC1JbmYsIHltYXggPSAwLCB4bWluID0gLUluZiwgeG1heCA9IEluZiwgZmlsbCA9ICdncmV5ODAnKSArDQogIGdlb21fcmVjdCh5bWluID0gMSwgeW1heCA9IEluZiwgeG1pbiA9IC1JbmYsIHhtYXggPSBJbmYsIGZpbGwgPSAnZ3JleTgwJykgKw0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gbSAtIHMsIHltYXggPSBtICsgcyksIHdpZHRoID0gMCkgKw0KICBnZW9tX3Ntb290aChhZXMoZ3JvdXAgPSAxKSwgbWV0aG9kID0gJ2xtJywgc2UgPSBGLCBmdWxscmFuZ2UgPSBUKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDEsIDAuMikpICsNCiAgZ2VvbV90ZXh0KGFlcyh5ID0gbWF4KG0pICsgbWF4KHMpLCBsYWJlbCA9IG4pKSArDQogIGxhYnMoeSA9ICdQKFdvQSBpcyBleHRyZW1lKScsDQogICAgICAgdGl0bGUgPSAnRXh0cmVtZSAoPC4wNSwgPi45NSkgV29BIHByb3BvcnRpb25zIGJ5IGRpc3RhbmNlJywNCiAgICAgICBzdWJ0aXRsZSA9ICdOdW1iZXJzIGF0IHRoZSB0b3Agc2hvdyB0aGUgbnVtYmVyIG9mIGNhc2VzIGluIGVhY2ggYmluJykNCg0KYGBgDQoNCldoaWxlIHdlIG91Z2h0IHRvIHRha2UgdGhlIGxhdHRlciBiaW5zIHdpdGggY2F1dGlvbiwgZ2l2ZW4gaG93IGZldyB0cmlhbHMgaGFkIHN1Y2ggZXh0cmVtZSBhZHZpY2UgZGlmZmVyZW5jZXMsIHdlIGNhbiBuZXZlcnRoZWxlc3Mgc2VlIGFuIGluY3JlYXNlIGluIHRoZSBwcm9wb3J0aW9uIG9mIGV4dHJlbWUgYWR2aWNlIHRha2luZyBhcyB0aGUgZGlzdGFuY2UgaW5jcmVhc2VzLg0KDQojIyBCeSBwYXJ0aWNpcGFudA0KDQpXZSB3YW50IHRvIGV4YW1pbmUgZGF0YSBieSBwYXJ0aWNpcGFudCB0byBzZWUgaWYgdGhleSBpbmRpdmlkdWFsbHkgc2hvdyB0aGUgcGF0dGVybi4gRm9yIGVhY2ggcGFydGljaXBhbnQgd2UgY2FuIGFzayBpZiB0aGUgcXVhZHJhdGljIG1vZGVsIGlzIGFuIGltcHJvdmVtZW50IG92ZXIgdGhlIGxpbmVhciBtb2RlbC4NCg0KYGBge3IgcGxvdHMgYnkgcGFydGljaXBhbnR9DQoNCmJ5UCA8LSBBZHZpc2VkVHJpYWwgJT4lDQogIG11dGF0ZShkaXN0ID0gYWR2aXNvcjBkaXN0YW5jZSwNCiAgICAgICAgIHdvYSA9IGFkdmlzb3Iwd29hLA0KICAgICAgICAgcCA9IGZhY3RvcihwYXN0ZShhcy5jaGFyYWN0ZXIoc3R1ZHlJZCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBhcy5jaGFyYWN0ZXIoc3R1ZHlWZXJzaW9uKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKHBpZCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICctJykpKSAlPiUNCiAgZ3JvdXBfYnkocCkgDQoNCiMgcnVuIG1vZGVscyBmb3IgZWFjaCBwYXJ0aWNpcGFudA0KbGluZWFyIDwtIGJ5UCAlPiUgDQogIGRvKG1vZGVsID0gbG0od29hIH4gZGlzdCwgZGF0YSA9IC4pKSANCg0KcXVhZHJhdGljIDwtIGJ5UCAlPiUgDQogIGRvKG1vZGVsID0gbG0od29hIH4gZGlzdCArIEkoZGlzdCBeIDIpLCBkYXRhID0gLikpIA0KDQpib3RoTW9kZWxzIDwtIGxlZnRfam9pbihnbGFuY2UobGluZWFyLCBtb2RlbCksIGdsYW5jZShxdWFkcmF0aWMsIG1vZGVsKSwgDQogICAgICAgICAgICAgICAgICAgICAgICBieSA9ICdwJywgc3VmZml4ID0gYygnLmxpbicsICcucXVhZCcpKSAlPiUNCiAgbXV0YXRlKGJlc3RNb2RlbCA9IGlmX2Vsc2UoQklDLnF1YWQgPiBCSUMubGluLCAnUXVhZHJhdGljJywgJ0xpbmVhcicpKSANCg0KY29lZnMgPC0gcmJpbmQoDQogIGxpbmVhciAlPiUgdGlkeShtb2RlbCkgJT4lIG11dGF0ZShtb2RlbCA9ICdsaW5lYXInKSwNCiAgcXVhZHJhdGljICU+JSB0aWR5KG1vZGVsKSAlPiUgbXV0YXRlKG1vZGVsID0gJ3F1YWRyYXRpYycpDQopDQoNCmJvdGhNb2RlbHMgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgc3VtbWFyaXNlKFAucXVhZE1vZGVsQmV0dGVyID0gbWVhbihiZXN0TW9kZWwgPT0gJ1F1YWRyYXRpYycpKQ0KDQpib3RoTW9kZWxzICU+JSBnYXRoZXIoJ21vZGVsJywgJ0JJQycsIA0KICAgICAgICAgICAgICAgICAgICAgIGMod2hpY2goZ3JlcGwoJ0JJQy4nLCBuYW1lcyhib3RoTW9kZWxzKSkpKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IG1vZGVsLCB5ID0gQklDKSkgKyANCiAgZ2VvbV92aW9saW4oKSArIA0KICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gcCwgY29sb3VyID0gYmVzdE1vZGVsID09ICdRdWFkcmF0aWMnKSwgDQogICAgICAgICAgICBhbHBoYSA9IC4xLCBwb3NpdGlvbiA9ICJqaXR0ZXIiKSArDQogIHNjYWxlX3lfbG9nMTAoKSArDQogIGxhYnMoeSA9ICdsb2cxMChCSUMpJykgDQoNCmBgYA0KDQpXZSBjYW4gYWxzbyBwbG90IHRoZSBiZXN0LWZpdHRpbmcgZnVuY3Rpb25zIGZvciBlYWNoIHBhcnRpY2lwYW50Lg0KDQpgYGB7ciBwYXJhbWV0ZXIgZXN0aW1hdGVzfQ0KDQpjb2VmcyAlPiUgZ2dwbG90KGFlcyh4ID0gImNvZWZmaWNpZW50IiwgeSA9IGVzdGltYXRlLCANCiAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBlc3RpbWF0ZSAtIHN0ZC5lcnJvciwNCiAgICAgICAgICAgICAgICAgICAgIHltYXggPSBlc3RpbWF0ZSArIHN0ZC5lcnJvcikpICsNCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9ICJqaXR0ZXIiLCBhbHBoYSA9IC4xKSArDQogIGZhY2V0X2dyaWQodGVybSB+IG1vZGVsLCBzY2FsZXMgPSAnZnJlZScpDQoNCnRtcCA8LSBjb2VmcyAlPiUgZHBseXI6OmZpbHRlcihtb2RlbCA9PSAicXVhZHJhdGljIikgJT4lDQogIGRwbHlyOjpzZWxlY3QocDplc3RpbWF0ZSkgJT4lDQogIHNwcmVhZCh0ZXJtLCBlc3RpbWF0ZSkgDQoNCmRhdGEgPC0gTlVMTA0KDQpmb3IgKHggaW4gMDoxMDApIHsNCiAgZGF0YSA8LSByYmluZChkYXRhLCB0aWJibGUoDQogICAgcCA9IHRtcCRwLA0KICAgIHgsDQogICAgaW50ZXJjZXB0ID0gdG1wJGAoSW50ZXJjZXB0KWAsDQogICAgZGlzdGFuY2UgPSB0bXAkZGlzdCwNCiAgICBkaXN0YW5jZVNxdWFyZWQgPSB0bXAkYEkoZGlzdF4yKWAsDQogICAgd29hID0gdG1wJGAoSW50ZXJjZXB0KWAgKyB0bXAkZGlzdCAqIHggKyB0bXAkYEkoZGlzdF4yKWAgKiAoeCBeIDIpDQogICkpDQp9DQoNCmRhdGEgJT4lIGRwbHlyOjpmaWx0ZXIod29hID4gMCAmIHdvYSA8IDEpICU+JQ0KICBnZ3Bsb3QoYWVzKHgsIHdvYSwgY29sb3VyID0gZGlzdGFuY2UgPiAwLCBncm91cCA9IHApKSArDQogIGdlb21fbGluZShhbHBoYSA9IC4yNSkgKw0KICBzY2FsZV9jb2xvdXJfZGlzY3JldGUoKSArIA0KICBzdGF0X2Z1bmN0aW9uKGZ1biA9IH4gYSArIGIgKiAueCArIGMgKiAoLnggXiAyKSwgY29sb3VyID0gJ3JlZCcpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ2JvdHRvbScpDQoNCmBgYA0KDQpUaGUgYWJvdmUgaXMgcHJldHR5IG1lc3N5IC0gd2UgY2FuIGluc3RlYWQgbG9vayBhdCB0aGlzIHdpdGhpbiBhIHBhcnRpY2lwYW50IGJ5IHNwbGl0dGluZyB1cCB0aGUgYWR2aWNlIHRoZXkgcmVjZWl2ZWQgaW50byBkaXN0YW5jZSBiaW5zIGFuZCBjb21wdXRpbmcgdGhlaXIgd2VpZ2h0IG9uIGFkdmljZSBieSBlYWNoIGJpbi4gVGhpcyBpcyBhIGxlc3Mgb2JqZWN0aXZlIG1lYXN1cmUsIGJ1dCBpdCBzZWVtcyBwbGF1c2libGUgdGhhdCBwYXJ0aWNpcGFudHMgY2FsaWJyYXRlIHRvIHRoZSBleHBlY3RlZCBkaXN0YW5jZXMgb2YgdGhlIGFkdmljZSBkdXJpbmcgdGhlIHRhc2suDQoNCmBgYHtyIHdvYSBieSBkaXN0YW5jZSB3aXRoaW4gcGFydGljaXBhbnR9DQoNCmJ5UCA8LSBieVAgJT4lDQogIG11dGF0ZShkaXN0YW5jZUJpbkJ5UCA9IGFzLm51bWVyaWMoY3V0KGRpc3QsIDUpKSkNCg0KYnlQJGRpc3RhbmNlQmluQnlQIDwtIGZhY3RvcihieVBbWydkaXN0YW5jZUJpbkJ5UCddXSkNCg0KIyByZW1vdmUgcGFydGljaXBhbnRzIHdpdGggZmV3ZXIgdGhhbiA1IGRpc3RhbmNlIGNhdGVnb3JpZXMNCnRtcCA8LSBieVAgJT4lIA0KICBncm91cF9ieShwLCBkaXN0YW5jZUJpbkJ5UCkgJT4lDQogIHN1bW1hcmlzZShkaXN0ID0gbWVhbihkaXN0KSkgDQp0bXAgPC0gYWdncmVnYXRlKGRpc3RhbmNlQmluQnlQIH4gcCwgdG1wLCBsZW5ndGgpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKGRpc3RhbmNlQmluQnlQIDwgNSkNCg0KYnlQc3ViIDwtIGJ5UCAlPiUgDQogIGRwbHlyOjpmaWx0ZXIocCAlaW4lIHRtcCRwKSAlPiUNCiAgdW5ncm91cChwKSAlPiUNCiAgbXV0YXRlKHAgPSBkcm9wbGV2ZWxzKHApKSAlPiUNCiAgZ3JvdXBfYnkocCkNCiAgDQoNCiMgbG9vayBhdCBkaXN0cmlidXRpb24gZm9yIGVhY2ggcGFydGljaXBhbnQNCmJ5UHN1YiAlPiUgZ2dwbG90KGFlcyh4ID0gZGlzdGFuY2VCaW5CeVAsIHkgPSBkaXN0LA0KICAgICAgICAgICAgICAgY29sb3VyID0gcCwgZ3JvdXAgPSBwKSkgKw0KICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICdwb2ludCcsIGZ1bi55ID0gbWVhbiwgYWxwaGEgPSAuMjUsIHBvc2l0aW9uID0gJ2ppdHRlcicpICsNCiAgc2NhbGVfY29sb3JfZGlzY3JldGUoZ3VpZGUgPSAnbm9uZScpICsNCiAgbGFicyh0aXRsZSA9IA0KICAgICAgICAgJ01lYW4gZGlzdGFuY2Ugb2YgdHJpYWwgaW4gZWFjaCBkaXN0YW5jZSBiaW4gZm9yIGVhY2ggcGFydGljaXBhbnQnKQ0KDQpgYGANCg0KYGBge3Igd29hIGJ5IGRpc3RhbmNlIHdpdGhpbiBhbmFseXNpc30NCg0KIyBydW4gbW9kZWxzIGZvciBlYWNoIHBhcnRpY2lwYW50DQpieVBzdWIkZGlzdGFuY2VCaW5CeVAgPC0gYXMubnVtZXJpYyhieVBzdWIkZGlzdGFuY2VCaW5CeVApDQoNCmxpbmVhciA8LSBieVBzdWIgJT4lIA0KICBkbyhtb2RlbCA9IGxtKHdvYSB+IGRpc3RhbmNlQmluQnlQLCBkYXRhID0gLikpIA0KDQpxdWFkcmF0aWMgPC0gYnlQc3ViICU+JSANCiAgZG8obW9kZWwgPSBsbSh3b2EgfiBkaXN0YW5jZUJpbkJ5UCArIEkoZGlzdGFuY2VCaW5CeVAgXiAyKSwgZGF0YSA9IC4pKSANCg0KYm90aE1vZGVscyA8LSBsZWZ0X2pvaW4oZ2xhbmNlKGxpbmVhciwgbW9kZWwpLCBnbGFuY2UocXVhZHJhdGljLCBtb2RlbCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAncCcsIHN1ZmZpeCA9IGMoJy5saW4nLCAnLnF1YWQnKSkgJT4lDQogIG11dGF0ZShiZXN0TW9kZWwgPSBpZl9lbHNlKEJJQy5xdWFkID4gQklDLmxpbiwgJ1F1YWRyYXRpYycsICdMaW5lYXInKSkgDQoNCmNvZWZzIDwtIHJiaW5kKA0KICBsaW5lYXIgJT4lIHRpZHkobW9kZWwpICU+JSBtdXRhdGUobW9kZWwgPSAnbGluZWFyJyksDQogIHF1YWRyYXRpYyAlPiUgdGlkeShtb2RlbCkgJT4lIG11dGF0ZShtb2RlbCA9ICdxdWFkcmF0aWMnKQ0KKQ0KDQpib3RoTW9kZWxzICU+JQ0KICB1bmdyb3VwKCkgJT4lDQogIHN1bW1hcmlzZShQLnF1YWRNb2RlbEJldHRlciA9IG1lYW4oYmVzdE1vZGVsID09ICdRdWFkcmF0aWMnKSkNCg0KYm90aE1vZGVscyAlPiUgZ2F0aGVyKCdtb2RlbCcsICdCSUMnLCANCiAgICAgICAgICAgICAgICAgICAgICBjKHdoaWNoKGdyZXBsKCdCSUMuJywgbmFtZXMoYm90aE1vZGVscykpKSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBtb2RlbCwgeSA9IEJJQykpICsgDQogIGdlb21fdmlvbGluKCkgKyANCiAgZ2VvbV9saW5lKGFlcyhncm91cCA9IHAsIGNvbG91ciA9IGJlc3RNb2RlbCA9PSAnUXVhZHJhdGljJyksIA0KICAgICAgICAgICAgYWxwaGEgPSAuMSwgcG9zaXRpb24gPSAiaml0dGVyIikgKw0KICBzY2FsZV95X2xvZzEwKCkgKw0KICBsYWJzKHkgPSAnbG9nMTAoQklDKScpIA0KDQoNCmBgYA0KDQoNCmBgYHtyIGJ5IGluZGl2aWR1YWwgYWR2aWNlIHNwZWN0cnVtIHBhcmFtZXRlciBlc3RpbWF0ZXN9DQoNCmNvZWZzICU+JSBnZ3Bsb3QoYWVzKHggPSAiY29lZmZpY2llbnQiLCB5ID0gZXN0aW1hdGUsIA0KICAgICAgICAgICAgICAgICAgICAgeW1pbiA9IGVzdGltYXRlIC0gc3RkLmVycm9yLA0KICAgICAgICAgICAgICAgICAgICAgeW1heCA9IGVzdGltYXRlICsgc3RkLmVycm9yKSkgKw0KICBnZW9tX3BvaW50KHBvc2l0aW9uID0gImppdHRlciIsIGFscGhhID0gLjEpICsNCiAgZmFjZXRfZ3JpZCh0ZXJtIH4gbW9kZWwsIHNjYWxlcyA9ICdmcmVlJykNCg0KdG1wIDwtIGNvZWZzICU+JSBkcGx5cjo6ZmlsdGVyKG1vZGVsID09ICJxdWFkcmF0aWMiKSAlPiUNCiAgZHBseXI6OnNlbGVjdChwOmVzdGltYXRlKSAlPiUNCiAgc3ByZWFkKHRlcm0sIGVzdGltYXRlKSANCg0KDQpjdXRzIDwtIHF1YW50aWxlKEFkdmlzZWRUcmlhbCRhZHZpc29yMGRpc3RhbmNlLCBzZXEoMCwgLjksIGxlbmd0aCA9IDYpKQ0KDQpkYXRhIDwtIE5VTEwNCm92ZXJhbGxNb2RlbCA8LSBOVUxMDQoNCmZvciAoeCBpbiAwOjUpIHsNCiAgZGF0YSA8LSByYmluZChkYXRhLCB0aWJibGUoDQogICAgcCA9IHRtcCRwLA0KICAgIGFkdmljZURpc3RhbmNlID0geCwNCiAgICBpbnRlcmNlcHQgPSB0bXAkYChJbnRlcmNlcHQpYCwNCiAgICBkaXN0YW5jZSA9IHRtcCRkaXN0YW5jZUJpbkJ5UCwNCiAgICBkaXN0YW5jZVNxdWFyZWQgPSB0bXAkYEkoZGlzdGFuY2VCaW5CeVBeMilgLA0KICAgIHdvYSA9IHRtcCRgKEludGVyY2VwdClgICsgDQogICAgICB0bXAkZGlzdGFuY2VCaW5CeVAgKiB4ICsgDQogICAgICB0bXAkYEkoZGlzdGFuY2VCaW5CeVBeMilgICogKHggXiAyKQ0KICApKQ0KICBvdmVyYWxsTW9kZWwgPC0gcmJpbmQob3ZlcmFsbE1vZGVsLCB0aWJibGUoDQogICAgYWR2aWNlRGlzdGFuY2UgPSB4LA0KICAgIGludGVyY2VwdCA9IGEsDQogICAgZGlzdGFuY2UgPSBiLA0KICAgIGRpc3RhbmNlU3F1YXJlZCA9IGMsDQogICAgd29hID0gYSArIGIgKiBjdXRzW3hdICsgYyAqIChjdXRzW3hdIF4gMikNCiAgKSkNCn0NCg0KZGF0YSAlPiUgI2RwbHlyOjpmaWx0ZXIod29hID4gMCAmIHdvYSA8IDEpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBhZHZpY2VEaXN0YW5jZSx5ID0gd29hLCBjb2xvdXIgPSBkaXN0YW5jZSA+IDAsIGdyb3VwID0gcCkpICsNCiAgZ2VvbV9saW5lKGFscGhhID0gLjI1KSArDQogIHNjYWxlX2NvbG91cl9kaXNjcmV0ZSgpICsgDQogIGdlb21fbGluZShkYXRhID0gb3ZlcmFsbE1vZGVsLCBjb2xvdXIgPSAncmVkJykgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJykNCg0KYGBgDQoNCiMgQ3JlZGl0cyANCg0KIyMgQWNrbm93bGVkZ2VtZW50cw0KDQpUaGFua3MgYXMgYWx3YXlzIHRvIE5pY2sgWWV1bmcgYW5kIHRoZSBvdGhlciBmb2xrcyBhdCB0aGUgW0FDQyBMYWJdKGh0dHBzOi8vd3d3LnBzeS5veC5hYy51ay9yZXNlYXJjaC9hdHRlbnRpb24tY29nbml0aXZlLWNvbnRyb2wtbGFiKS4NCg0KIyMgUiBQYWNrYWdlcw0KDQpgYGB7ciByZXN1bHRzID0gJ2FzaXMnfQ0KIyBsaXN0IHBhY2thZ2VzDQpwYWNrYWdlTmFtZXMgPC0gKC5wYWNrYWdlcygpKQ0KIyBkb24ndCBpbmNsdWRlIHZlcnkgY29yZSBwYWNrYWdlDQpwYWNrYWdlTmFtZXMgPC0gcGFja2FnZU5hbWVzWyEocGFja2FnZU5hbWVzICVpbiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW9yaXR5ID0gImJhc2UiKSkpXQ0KIyBidXQgZG8gaW5jbHVkZSB0aGUgYmFzZSBwYWNrYWdlDQpwYWNrYWdlTmFtZXMgPC0gYygiYmFzZSIsIHBhY2thZ2VOYW1lcykNCm91dCA8LSBOVUxMDQpmb3IgKHAgaW4gcGFja2FnZU5hbWVzKSB7DQogIG91dCA8LSByYmluZChvdXQsIGRhdGEuZnJhbWUoJ1BhY2thZ2UnID0gcCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0NpdGF0aW9ucycgPSBwYXN0ZShmb3JtYXQoY2l0YXRpb24ocCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlID0gJ3RleHRWZXJzaW9uJyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSAnPGJyLz48YnIvPicpKSkNCn0NCg0Ka2FibGUob3V0KQ0KYGBgDQoNCiMjIEZ1bmRpbmcNCg0KTWF0dCBKYXF1aWVyeSBpcyBmdW5kZWQgYnkgYSBzdHVkZW50c2hpcCBmcm9tIHRoZSBbTWVkaWNhbCBSZXNlYXJjaCBDb3VuY2lsXShodHRwczovL21yYy51a3JpLm9yZy8pIChyZWZlcmVuY2UgMTk0MzU5MCkgYW5kIHRoZSBVbml2ZXJzaXR5IG9mIE94Zm9yZCBbRGVwYXJ0bWVudCBvZiBFeHBlcmltZW50YWwgUHN5Y2hvbG9neV0oaHR0cHM6Ly93d3cucHN5Lm94LmFjLnVrLykgKHJlZmVyZW5jZSAxNy8xOF9NU0RfNjYxNTUyKS4NCg0KIyMgVGVjaG5pY2FsIGRldGFpbHMgIA0KDQpgYGB7ciByZXN1bHRzID0gJ2hvbGQnfQ0KY2F0KHBhc3RlKCdUaW1lIHN0YW1wOicsIFN5cy50aW1lKCksICdcblxuJykpDQpjYXQoJ1J1bnRpbWUgXG4nKQ0KcHJvYy50aW1lKCkNCmNhdCgnXG4nKQ0Kc2Vzc2lvbkluZm8oKQ0KYGBg